#include <iostream>
#include <fstream>
#include <cstring>

#include "swt_env_win_linux.h"
#include "lct_env_macros.h"
#include "FileManagement.h"


#ifdef _SWT_WIN32_
#define M_PI  3.1415926535897932
#endif


#ifdef USE_GNU_COMPILER
// create data directory; 2007.07.23, sun weitao
int createdatadir(const char RltDataDir[_MAX_PATH],
                  const char user_code_tag[],
                  const char MainMark[_MAX_PATH],
                  char level3_mark[_MAX_PATH],
                  char outdir[_MAX_PATH],//char out_domain_name[_MAX_PATH],char in_date[],
                  int level,int verbose)
{

    printf("Begin: --------- CreateDataDir --------------\n");
    char rootdir[500]={""},rootdir2[500]={""},rootdir3[500]={""}; // mydate[222],
    if(level<1||level>3) level=2;

    int l=strlen(RltDataDir);


    char rootdir_full[500];
    swt_fullpath(RltDataDir,rootdir_full, 1);




    if( RltDataDir[l-1]==SWT_SLASH )
        sprintf(rootdir,"%s%s",//_%s_%s",
                rootdir_full,user_code_tag);// username, exefilename,in_date );	//set dir name;
    else
        sprintf(rootdir,"%s%c%s",//_%s_%s",
                rootdir_full,SWT_SLASH, user_code_tag);//username, exefilename,mydate );

    printf("to make folder:\t%s ......\n",rootdir);




    //create level one dir;
    if( swt_mkdir(rootdir) == 0 )
    {//success;
        if(verbose)
            printf( "folder '%s' was successfully created\n",MainMark);
        if( swt_chdir( rootdir) == 0 )
        {
            if(verbose)
                printf( "Directory '%s' was successfully in\n",MainMark  );
        }
        else
        {
            if(createdirerror(rootdir,verbose)<=0)
            {
                printf("CreateDataDir level 1 failed: %s\n",rootdir);
                return -1;
            }
        }

    }
    else
    {  //fail;
        if( swt_chdir( rootdir) == 0 )
        {
            if(verbose)
                printf( "folder\t'%s' already exists.\n",MainMark  );
        }
        else if(  createdirerror(rootdir,verbose)<=0)
        {
            printf("Create folder level 1 failed: %s\n",rootdir);
            return -1;
        }

    }

    if(level==1)
    {
        sprintf (outdir,"%s",rootdir);
        printf("create folder level 1 ok:\t%s\n",outdir);
        return 1;
    }

    //make second level dir;
    l=strlen(rootdir);
    if( rootdir[l-1]==SWT_SLASH )
        sprintf(rootdir2,"%s%s",rootdir, MainMark);
    else
        sprintf(rootdir2,"%s%c%s",rootdir,SWT_SLASH, MainMark);

    printf("to create folder:\t%s ......\n",rootdir2);

    swt_fullpath(rootdir2,rootdir2);
    if( swt_mkdir(rootdir2) == 0 )
    {
        if(verbose) printf( "folder\t'%s' was successfully created\n",MainMark );
        if( swt_chdir( rootdir2) == 0 )
            if(verbose) printf( "come into folder\t'%s'\n",MainMark  );
            else
            {
                if(createdirerror(rootdir,verbose)<=0)
                {
                    printf("CreateDataDir level 2 failed: %s\n",rootdir);
                    return -1;
                }
            }
    }
    else
    {
        if( swt_chdir( rootdir2) == 0 )
        {
            if(verbose)
                printf( "folder\t'%s' already exists.\n",MainMark  );
        }
        else if(createdirerror( rootdir2,verbose) <=0)
        {
            printf("folder level 2 failed: %s\n",rootdir);
            return -1;
        }
    }


    if(level==2)
    {
        sprintf (outdir,"%s",rootdir2);
        printf("Create level 2 folder %s ok.\n",outdir);
        return 1;
    }

    //make third level dir;
    l=strlen(rootdir2);
    if( rootdir2[l-1]==SWT_SLASH )
        sprintf(rootdir3,"%s%s",rootdir2, level3_mark);
    else
        sprintf(rootdir3,"%s%c%s",rootdir2,SWT_SLASH, level3_mark);

    printf("current data dir=%s\n",rootdir3);


    if( swt_mkdir(rootdir3) == 0 )
    {
        if(verbose) printf( "Directory '%s' was successfully created\n",level3_mark );
        if( swt_chdir( level3_mark) == 0 )
            if(verbose) printf( "Directory '%s' was successfully in\n",level3_mark  );
            else
            {
                if(createdirerror(rootdir2,verbose)<=0)
                {
                    printf("CreateDataDir level 3 failed: %s\n",rootdir2);
                    return -1;
                }
            }
    }
    else
    {
        if( swt_chdir( rootdir3) == 0 )
        {
            if(verbose)
                printf( "Directory '%s' was successfully \n",MainMark  );
        }
        else
        if(createdirerror( rootdir3,verbose) <=0)
        {
            printf("CreateDataDir level 3 failed: %s\n",rootdir2);
            return -1;
        }
    }

    sprintf (outdir,"%s",rootdir3);

    printf("CreateDataDir level 3 ok: %s\n",outdir);
    printf("End: --------- CreateDataDir --------------\n");

    return 1;

}

int swt_mkdir(char dir[],size_t mode)
{
    int rtv=0;
#ifdef _SWT_WIN32_
    rtv=_mkdir(dir);
#else
    rtv=mkdir(dir,mode);
#endif
    return rtv;
}

int createdirerror( char rootdir2[],int verbose)
{
    if(errno==EEXIST)
    {  if(verbose)
            printf( "Directory '%s' exist.\n",rootdir2 );
        return 1;
    }
    else if(errno==ENOENT)
    {
        if(verbose)
            printf( "Directory '%s', A directory component in pathname does not exist or is a dangling symbolic link. \n",rootdir2 );
    }
    else if(errno==EACCES)
    {
        if(verbose)
            printf( "Directory '%s', the parent directory does not allow write permission to the process, or one of the directories in pathname did not allow search permission. (See also path_resolution(2).)\n",rootdir2 );
    }
    else if(errno==EFAULT )
    {
        if(verbose)
            printf( "Directory '%s', pathname points outside your accessible address space. \n",rootdir2 );
    }
    else if(errno==ENAMETOOLONG  )
    {
        if(verbose)
            printf( "Directory '%s', pathname was too long. \n",rootdir2 );
    }
    else if(errno==ENOMEM )
    {
        if(verbose)
            printf( "Directory '%s', Insufficient kernel memory was available. \n",rootdir2 );
    }
    else if(errno==ENOSPC )
    {
        if(verbose)
            printf( "Directory '%s', The device containing pathname has no room for the new directory. \n",rootdir2 );
    }
    else if(errno==ENOTDIR  )
    {
        if(verbose)
            printf( "Directory '%s', A component used as a directory in pathname is not, in fact, a directory. \n",rootdir2 );
    }
    else if(errno==EPERM   )
    {
        if(verbose)
            printf( "Directory '%s', The filesystem containing pathname does not support the creation of directories. \n",rootdir2 );
    }
    else if(errno==EROFS    )
    {
        if(verbose)
            printf( "Directory '%s', pathname refers to a file on a read-only filesystem. \n",rootdir2 );
    }
    else
    {
        if(verbose)  printf( "Unkown problem creating directory or directory '%s' exist.\n",rootdir2 );
        return -1;
    }
    return 0;
}


//get the username+binary file+date tag.
//weitao sun, 2010.7.7
int swt_fun_util_create_code_tag(char tag_out[],char username_out[],
                                 char domainname_out[],int verbose)
{
    char username[_MAX_PATH]={""},
            domainname[_MAX_PATH]={""},
            exefilename[_MAX_PATH]={""},
            mydate[_MAX_PATH]={""};

    gettime(mydate);
    swt_getusername(username, domainname, 1);		//get current user name;
    swt_getmodulefilename(exefilename);	//get current module name;

    if(verbose)
        printf("Username=%s\tdomain_name=@%s\n",username,domainname);

    char tag[_MAX_PATH]={""};
    sprintf(tag,"%s_%s_%s",
            username, exefilename,mydate);	//set dir name;

    if(tag_out!=NULL)
        strcpy(tag_out,tag);
    if(username_out!=NULL)
        strcpy(username_out,username);
    if(domainname_out!=NULL)
        strcpy(domainname_out,domainname);

    return 1;
}
int fun_csaw_create_dir(const char RltDataDir[], const char fileid[],
                        int mpi_myid, int round_i, char outdir[], char domain_name[], char date[])

{

    //5) create data directory and data files; 2007.07.23, sun weitao;
    //file names and create data IO directory;
    //char outdir[_MAX_PATH]={""},

    //char	date[_MAX_PATH]={""},

    //char FileMainMark[_MAX_PATH]={""};

    int create_ok=0;
    char current_folder[_MAX_PATH]={""};
    SWT_GetCurrentDirectory(current_folder);
//////////////////////////////////////////////////////////////////////////

//--------------------- START: MPI Process ---- 2008.03.13 by W. Sun -----

//////////////////////////////////////////////////////////////////////////

    if(mpi_myid==0)
    {
        //root node create data:
        //	1. date[]; 2. outdir[]; 	3. FileMainMark[];
        //	if create dir failed;
        //	3. cp->fileid;			4.	cp->NativePdbfile;
        //	5. cp->SnapshotFile;	6.  cp->RltDataDir;

        if(date==NULL)
            gettime(date); //get current date;

        //create output data directory;
        char dir_id[_MAX_PATH]={""}, user_tag[_MAX_PATH]={""};

        swt_fun_util_create_code_tag(user_tag,NULL,domain_name);
        sprintf(dir_id,"round%d",  round_i);

        create_ok=createdatadir(RltDataDir,user_tag, fileid,dir_id,outdir,2,1);

    }

    //go back to original folder;
    swt_chdir(current_folder);
    printf("change to origin folder %s\n",current_folder);

    //root node failed to create data directory, all nodes exit;
    if(create_ok!=1)
    {
        printf("ERROR_ERROR_ERROR_ERROR_ERROR_ERROR_ERROR_ERROR_ERROR\n");
        printf("MYID=%d\tCreate data directory failed.\n",mpi_myid);
        printf("ERROR_ERROR_ERROR_ERROR_ERROR_ERROR_ERROR_ERROR_ERROR\n");

        return 0;

    }

//////////////////////////////////////////////////////////////////////////

//--------------------- START: MPI Process ---- 2008.03.13 by W. Sun -----

//////////////////////////////////////////////////////////////////////////

// #ifdef  _SWT_MPI_
// 	MPI_Bcast(date,_MAX_PATH,MPI_CHAR,0,MPI_COMM_WORLD);
// 	MPI_Bcast(outdir,_MAX_PATH,MPI_CHAR,0,MPI_COMM_WORLD);
// #endif

    return create_ok;

}

int gettime(char date[], int format)
{

    time_t ltime;
    struct tm *newtime;
    if(format==0)
    {
        time( &ltime );
        newtime = localtime( &ltime );
        sprintf(date, "%d.%d.%d", 1900+newtime->tm_year ,1+newtime->tm_mon ,newtime->tm_mday    );
    }
    else if(format==1)
    {
        /* Get UNIX-style time and display as number and string. */
        time( &ltime );
        //sprintf( "Time in seconds since UTC 1/1/70:\t%ld\n", ltime );
        sprintf(date, "%s", ctime( &ltime ) );

    }
    else if(format==2)
    {
        time( &ltime );
        newtime = localtime( &ltime );
        sprintf(date, "%d%02d%02d", 1900+newtime->tm_year ,1+newtime->tm_mon ,newtime->tm_mday    );
    }
    else
    {
        /* Display UTC. */

        newtime = gmtime( &ltime );
        sprintf( date, "%s", asctime( newtime ) );

    }

    return  1;
}



//get username
int swt_getusername(char *username,char *domainname,int verbose)
{
    int len_name=0, len_domain_name=0;
    strcpy(username,"unknown");
    if(verbose)
        printf("Default username is %s\n",username);

#ifdef _SWT_WIN32_
    //	DWORD nsize=0;
	//bool ok=GetUserName(username,&nsize);
	if(verbose)
		printf("Get Windows system username:	");

	bool ok=GetCurrent_UserName_Domain(username,domainname);
	if(ok)	len_name=strlen(username);

	if(verbose)
		printf("%s\n",username);

#elif defined _SWT_XWIN_
    if(verbose)
        printf("Get Linux/Unix system username:	");
    passwd *user=getpwuid(getuid());
    strcpy(username,user->pw_name);
    len_name=strlen(username);

    if(verbose)
        printf("%s\n",username);

    //get domain name;
    char domain_name[550]={""},hostname[32]={""};

    if(domainname!=NULL)
    {

        if( gethostname(hostname,sizeof(hostname)) )
        {
            printf("gethostname calling error\n");
            // return 1;
        }
        else
        {
            strcpy(domainname,hostname);
            if(verbose)
                printf("domain name: %s\n",domainname);
        }
    }


#else
    strcpy(username,"unknown");
	len_name=0;
#endif

    return len_name;
}
int swt_getmodulefilename(char filename[],int is_fullname)
{
    char exeFullPath[_MAX_PATH];
#ifdef _SWT_WIN32_
    GetModuleFileName(NULL,exeFullPath,_MAX_PATH);
	//	return 1;
#elif defined _SWT_XWIN_
    GetModuleFileName_Linux(exeFullPath,_MAX_PATH);
#endif

    printf("Current module name is: %s\n",exeFullPath);
    if(is_fullname==1)
        strcpy(filename,exeFullPath);
    else if(is_fullname==0)
        DelPath(exeFullPath,filename);
    else
        DelPath(exeFullPath,filename);

    DelFileExt(filename,filename);
    return 1;
}

bool GetCurrent_UserName_Domain(char *username,char *domainname)
{
    sprintf(username,"unknown");
#ifdef _SWT_WIN32_

    HANDLE hToken;

	//�õ�shell��token
	if(!GetTokenByName(hToken,"EXPLORER.EXE"))
	{
		return FALSE;
	}
	DWORD        cbti     = 0;
	PTOKEN_USER  ptiUser  = NULL;
	SID_NAME_USE snu;

	//ȡ������ռ��С
	if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti))
	{
		CloseHandle(hToken);
		return FALSE;
	}

	//����ռ�
	ptiUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbti);
	if(!ptiUser)
	{
		CloseHandle(hToken);
		return FALSE;
	}

	//ȡ��token��Ϣ
	if (!GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti))
	{
		CloseHandle(hToken);
		HeapFree(GetProcessHeap(), 0, ptiUser);
		return FALSE;
	}

	char szUser[50];
	char szDomain[50];
	DWORD nUser = 50;
	DWORD nDomain = 50;

	//�����û���sid�õ��û�����domain

	if (!LookupAccountSid(NULL, ptiUser->User.Sid, szUser, &nUser,
		szDomain, &nDomain, &snu))
	{
		CloseHandle(hToken);
		HeapFree(GetProcessHeap(), 0, ptiUser);
		return FALSE;
	}


	OutputDebugString(szUser);
	OutputDebugString("\r\n");
	OutputDebugString(szDomain);
	OutputDebugString("\r\n");

	strcpy(username,szUser);
	if(domainname!=NULL) strcpy(domainname,szDomain);

	CloseHandle(hToken);
	HeapFree(GetProcessHeap(), 0, ptiUser);
#endif
    return true;
}

int DelPath(const char filein[],char fileout[],int verbose)
{
    char driver[_MAX_PATH];
    char dir [_MAX_PATH];
    char filename[_MAX_PATH];
    char ext[_MAX_PATH];
    char tmp_fileout[_MAX_PATH]={""};

    if(verbose)
        printf("Delete file path...: %s\n",filein);
#ifdef _SWT_WIN32_
    _splitpath(filein,driver,dir ,filename,ext);
#else
    swt_splitpath(filein,driver,dir,filename,ext);
#endif
    strcpy(tmp_fileout,filename);
    strcat(tmp_fileout,ext);

    if(fileout!=NULL)
        strcpy(fileout, tmp_fileout);
    //	else
    //		strcpy(filein,tmp_fileout);

    if(verbose)
        printf("Delete file path...End. (%s)\n",tmp_fileout);
    return 1;

}

int DelFileExt(char  file[],char fileout[],int verbose)
{
    char driver[100];
    char dir [400];
    char filename[200];
    char extn[100];
#ifdef _SWT_WIN32_
    _splitpath(file,driver,dir ,filename,extn);
#else
    swt_splitpath(file,driver,dir,filename,extn);
#endif

    int l1=strlen(file);
    int l2=strlen(extn);

    if(fileout==NULL)
    {
        file[l1-l2]='\0';
    }
    else
    {
        strcpy(fileout,file);
        fileout[l1-l2]='\0';
    }
    if(verbose)
        printf("Delete file extended name for %s\n",file);
    return 1;
}

//���ݽ������Ƶõ�����token
#ifdef _SWT_WIN32_

BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName)
{
	if(!lpName)
	{
		return FALSE;
	}
	HANDLE         hProcessSnap = NULL;
    BOOL           bRet      = FALSE;
    PROCESSENTRY32 pe32      = {0};

    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE)
        return (FALSE);

    pe32.dwSize = sizeof(PROCESSENTRY32);

    if (Process32First(hProcessSnap, &pe32))
    {
        do
        {
			if(!strcmp(_strupr(pe32.szExeFile),_strupr(lpName)))
			{
				HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
					FALSE,pe32.th32ProcessID);
				bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken);
				CloseHandle (hProcessSnap);
				return (bRet);
			}
        }
        while (Process32Next(hProcessSnap, &pe32));
        bRet = TRUE;
    }
    else
        bRet = FALSE;

    CloseHandle (hProcessSnap);
    return (bRet);
}
#endif


//get full path of input path 'pathin';
int swt_fullpath(const char pathin[],char pathout[],int verbose)
{
    char tmp_path_out[_MAX_PATH]={""};

#ifdef _SWT_WIN32_
    _fullpath(tmp_path_out,pathin,_MAX_PATH);

	if(pathout==NULL)
	{
		//		strcpy(pathout, tmp_path_out);
		return 0;
	}
	else
		strcpy(pathout,tmp_path_out);

	return 1;

#elif defined _SWT_XWIN_

    if(verbose)
        printf("In swt_fullpath(): XWINDOW version.\n");
    char tmpdir[_MAX_PATH];

    // realpath(pathin,tmpdir);
    strcpy(tmpdir, pathin);

    if(tmpdir!=NULL)
    {
        if(verbose)
            printf("In swt_fullpath(): full path is '%s'\n",tmpdir);

        strcpy(tmp_path_out,tmpdir);

        if(pathout==NULL)
        {
            //strcpy(pathout,tmp_path_out);
            return 0;
        }
        else
            strcpy(pathout,tmp_path_out);
        return 1;
    }
    else
    {
        if(verbose)
            printf("In swt_fullpath(): Can't find full path for '%s'\n",pathin);
        strcpy(tmp_path_out,pathin);
        if(pathout==NULL)
        {
            //	strcpy(pathin,tmp_path_out);
            return 0;
        }
        else
            strcpy(pathout,tmp_path_out);


        return 0;
    }
#endif
    return 1;
}


//get module file name in linux;
#ifdef _SWT_XWIN_

int GetModuleFileName_Linux(char* name, int size)
{
    FILE* stream = fopen("/proc/self/cmdline", "r");
    fgets(name, size, stream);
    fclose(stream);

    return strlen(name);
}



#endif
void swt_splitpath(const char* path, char* drv, char* dir, char* name, char* ext)
{
    const char* end; /* end of processed string */
    const char* p;   /* search pointer */
    const char* s;   /* copy pointer */

    /* extract drive name */
    if (path[0] && path[1]==':') {
        if (drv) {
            *drv++ = *path++;
            *drv++ = *path++;
            *drv = '\0';
        }
    } else if (drv)
        *drv = '\0';

    /* search for end of string or stream separator */
    for(end=path; *end && *end!=':'; )
        end++;

    /* search for begin of file extension */
    for(p=end; p>path && *--p!='\\' && *p!='/'; )
        if (*p == '.') {
            end = p;
            break;
        }

    if (ext)
        for(s=end; (*ext=*s++); )
            ext++;

    /* search for end of directory name */
    for(p=end; p>path; )
        if (*--p=='\\' || *p=='/') {
            p++;
            break;
        }

    if (name) {
        for(s=p; s<end; )
            *name++ = *s++;

        *name = '\0';
    }

    if (dir) {
        for(s=path; s<p; )
            *dir++ = *s++;

        *dir = '\0';
    }
}


//get current director name, with slash;
bool SWT_GetCurrentDirectory(char *currentdir)
{
    char dir[_MAX_PATH];
    int ok=0;
    sprintf(currentdir,"%c",SWT_SLASH);

#ifdef _SWT_WIN32_
    ok=GetCurrentDirectory(_MAX_PATH,dir);
	if(ok!=0)	strcpy(currentdir,dir);
#elif defined _SWT_XWIN_
    char *xok;
    xok=getcwd(dir,_MAX_PATH);
    if(xok!=NULL){
        strcpy(currentdir,dir);
        ok=1;
    }
#endif
    bool success=false;
    if(ok==1)
        success=true;
    return success;
}

#endif // USE_GNU_COMPILER
